import { ref, markRaw } from 'vue'
import { vec2, vec3, mat2d } from '@/libs/glmatrix/gl-matrix.js'
import { Tween, Easing } from '@tweenjs/tween.js'
export class FlipPage {
  constructor() {
    this.list = ref([])
    this.current = 0
    this.isStart = false
    this.init()
  }
  init() {
    let total = 10
    for (var i = 0; i < total / 2; i++) {
      let flip = markRaw(
        new FlipUI({
          page: i,
          total: 10,
          front: require('../../../images/page-' + (i * 2 + 1) + '.jpg'),
          back: require('../../../images/page-' + (i * 2 + 2) + '.jpg')
        })
      )
      this.list.value.push(flip)
    }
  }
  getCurrent(e) {
    let [touch] = e.touches
    let current = this.current
    let go = 0
    if (touch.clientX < window.innerWidth / 2) {
      current = current - 1
      go = 0
    }
    return {
      current,
      go
    }
  }
  onStart(e) {
    if (!this.isStart) {
      console.log(`开始`)
      let { current, go } = this.getCurrent(e)
      let fp = this.list.value[current]
      if (fp) {
        this.isStart = true
        this.current_temp = current
        fp.onStart(e)
        fp.calZ(go)
        this.direction = fp.direction
      }
    }
  }
  onEnd(e) {
    if (this.isStart) {
      let fp = this.list.value[this.current_temp]
      let prev_direction = this.direction
      this.isLock = true
      fp.onEnd(e, {
        complete: (flip) => {
          //当前页翻过了
          let end_direction = flip.direction

          console.log(`prev_direction`, prev_direction, 'end_direction', end_direction)

          if (prev_direction == 0 && end_direction == 1) {
            this.current++
          } else if (prev_direction == 1 && end_direction == 0) {
            //反向不需要，因为选中的就是当前的
            this.current--
          }
          console.log(`onEnd`, this.current)
          this.isStart = false
          this.isLock = false
        }
      })
    }
  }
  onMove(e) {
    if (this.isStart && !this.isLock) {
      let fp = this.list.value[this.current_temp]
      fp.onMove(e)
    }
  }
  next() {
    let fp = this.list.value[this.current]
    fp.toLeft(null, {
      complete: () => {
        this.current++
      }
    })
  }
  prev() {
    let fp = this.list.value[this.current - 1]
    fp.toRight(null, {
      complete: () => {
        this.current--
      }
    })
  }
}

export default class Flip {
  constructor(options) {
    this.options = {
      w: 200,
      h: 200
    }
    this.e_point = [0, 0]
    this.s_point = [0, 0]
    this.rect = ref({})
    this.rect_front_matrixs = []
    this.rect_back_matrixs = []
    this.direction = 0
    this.page = options.page
    this.page_total = options.total
    this.style = ref({})
    this.z = ref(0)
    this.vertical = 0
    this.init()
    this.c_s_point = this.corrds.rt
    this.c_e_point = this.corrds.rt
    this.calZ(this.direction)
  }
  calZ(direction) {
    let pow = Math.log(this.page_total) / Math.log(10)
    let z = 0
    pow = Math.ceil(pow) + 1
    //左边，页面小最大
    if (direction == 0) {
      z = Math.pow(10, pow) - this.page
    } else {
      z = this.page
      //右边看完的页数小，最小，再最下面
    }
    this.z.value = z
    this.style.value = {
      transform: `translatez(${z}px)`
    }
    console.log(this.style.value)
  }
  getZ() {
    this.calZ(this.direction)
    return this.z
  }
  init() {
    let { w, h } = this.options
    let lt = [-w / 2, -h / 2]
    let rt = [w / 2, -h / 2]
    let lb = [-w / 2, h / 2]
    let rb = [w / 2, h / 2]
    this.corrds = {
      lt,
      rt,
      lb,
      rb
    }

    //console.log(this.corrds)
  }
  inRange(point) {
    let [x, y] = point
    let { w, h } = this.options
    if (this.direction == 0) {
      if (x <= w / 2) {
        return true
      } else {
        return false
      }
    }
    if (this.direction == 1) {
      if (x >= (-w / 2) * 3) {
        return true
      } else {
        return false
      }
    }
  }
  calculate_style(rect) {
    let { w, h } = this.options
    let front_style = ''
    let back_style = {
      'clip-path': `polygon(0 0,0 0,0 0,0 0)`
    }

    if (rect.front.length) {
      let front = rect.front
        .map((res) => {
          let [x, y] = res
          return [x + w / 2, y + h / 2]
        })
        .map((res) => {
          let [x, y] = res
          return x + 'px' + ' ' + y + 'px'
        })

      front_style = {
        'clip-path': `polygon(${front.join(',')})`
      }

      let back = rect.back
        .map((res) => {
          let [x, y] = res
          return [x + w / 2, y + h / 2]
        })
        .map((res) => {
          let [x, y] = res
          return x + 'px' + ' ' + y + 'px'
        })

      let matrix = 'matrix(' + rect.back_flip_matrix.join(',') + ')'
      back_style = {
        'clip-path': `polygon(${back.join(',')})`,
        transform: matrix
      }
      return {
        front: front_style,
        back: back_style
      }
    } else {
      return this.rect.value
    }
  }
  toLeft(cb, options) {
    let [x, y] = this.c_e_point
    let end
    if (this.vertical == 0) {
      end = this.corrds.lt
    } else {
      end = this.corrds.lb
    }
    let [x0, y0] = end
    let { w, h } = this.options
    let obj = {
      x,
      y
    }
    let isStop = false
    const tween = new Tween(obj, false)
      .to(
        {
          x: (-w / 2) * 3,
          y: y0
        },
        300
      )
      .easing(Easing.Quadratic.InOut)
      .onUpdate(() => {
        //console.log(res)
        const res = this._calculate(this.c_s_point, [obj.x, obj.y])
        cb && cb(res)
      })
      .onComplete((res) => {
        this.direction = 1
        isStop = true
        this.calZ(1)
        options && options.complete(this)
      })
      .start()

    // Setup the animation loop.
    function animate(time) {
      if (!isStop) {
        tween.update(time)
        requestAnimationFrame(animate)
      }
    }
    requestAnimationFrame(animate)
  }
  toRight(cb, options) {
    this.calZ(0)
    let [x, y] = this.c_e_point
    let end
    if (this.vertical == 0) {
      end = this.corrds.rt
    } else {
      end = this.corrds.rb
    }
    let [x0, y0] = end
    let { w, h } = this.options
    let obj = {
      x,
      y
    }
    let isStop = false
    console.log('toRight', x0, y0, w / 2, -h / 2)
    const tween = new Tween(obj, false)
      .to(
        {
          x: x0,
          y: y0
        },
        300
      )
      .easing(Easing.Quadratic.InOut)
      .onUpdate(() => {
        //console.log(res)
        //console.log(obj.x, obj.y, this.c_s_point)
        const res = this._calculate(this.c_s_point, [obj.x, obj.y])
        cb && cb(res)
      })
      .onComplete((res) => {
        this.direction = 0
        options && options.complete(this)
        isStop = true
        this.calZ(0)
      })
      .start()

    // Setup the animation loop.
    function animate(time) {
      if (!isStop) {
        tween.update(time)
        requestAnimationFrame(animate)
      }
    }
    requestAnimationFrame(animate)
  }
  toEnd(cb, options) {
    //判断去哪里
    let { c_e_point } = this
    let [cx] = c_e_point
    let { w } = this.options
    if (this.direction == 0) {
      if (cx < 0) {
        this.toLeft(cb, options)
      } else {
        this.toRight(cb, options)
      }
    }
    if (this.direction == 1) {
      if (-cx < w) {
        this.toRight(cb, options)
      } else {
        this.toLeft(cb, options)
      }
    }
  }
  _fix_s_e_point(s_point, e_point) {
    //修正范围
    let [x0, y0] = s_point
    let [x1, y1] = e_point
    //修正角度
    if (this.direction == 0) {
      let v = vec2.create()
      vec2.sub(v, s_point, e_point)
      let rad = vec2.angle(v, [1, 0])

      //let cross = vec3.create()
      let angle = (rad / Math.PI) * 180
      //vec2.cross(cross, e_point, s_point)
      //console.log(`angle`, angle)
      if (angle <= 45) {
      } else {
        if (this.vertical == 0) {
          y1 = y0 + v[0]
        }
        if (this.vertical == 1) {
          y1 = y0 - v[0]
        }
        e_point[1] = y1
        return [s_point, e_point]
      }
    }
    if (this.direction == 1) {
      let v = vec2.create()
      let { w } = this.options
      let { lt } = this.corrds
      let s_p = [lt[0] - w / 2, lt[1]]
      vec2.sub(v, e_point, s_p)
      //console.log(`lt`, lt, e_point, s_p, v)
      let rad = vec2.angle(v, [1, 0])

      //let cross = vec3.create()
      let angle = (rad / Math.PI) * 180
      console.log(`angle`, angle)
      //vec2.cross(cross, e_point, s_point)
      //console.log(`angle`, angle)
      //if (angle <= 45) {
      //} else {
      //if (this.vertical == 0) {
      //y1 = y0 + v[0]
      //}
      //if (this.vertical == 1) {
      //y1 = y0 - v[0]
      //}
      //e_point[1] = y1
      //return [s_point, e_point]
      //}
    }
    return [s_point, e_point]
  }
  _calculate(s_point, e_point) {
    let { lt, lb, rb, rt } = this.corrds
    let { w, h } = this.options

    this.c_s_point = s_point
    this.c_e_point = e_point

    let center,
      rect_back = [],
      rect_front = [],
      back_flip_matrix = mat2d.create()

    if (this.inRange(e_point)) {
      let x = (s_point[0] + e_point[0]) / 2
      let y = (s_point[1] + e_point[1]) / 2
      center = [x, y]
      let k1, k2
      //console.log(`s_point`, s_point, `e_point`, e_point)
      if (e_point[0] - s_point[0] == 0) {
        //为0
        //console.log(`y = ?`)
      } else if (e_point[1] == s_point[1]) {
        //console.log('x = ?')
        rect_back = [[x, -h / 2], rt, rb, [x, h / 2]]
        rect_front = [lt, [x, -h / 2], [x, h / 2], lb]
        let m1 = [x, -h / 2]
        let m2 = [x, h / 2]
        //y轴对称重合，直接使用scale(-1,1) MOVE FLIP -MOVE
        let flip_center = [x, 0]

        let m = mat2d.create()
        mat2d.translate(m, m, [x, 0])
        mat2d.scale(m, m, [-1, 1])
        mat2d.translate(m, m, [-x, 0])
        back_flip_matrix = m
      } else {
        k1 = (e_point[1] - s_point[1]) / (e_point[0] - s_point[0])
        k2 = -1 / k1
        //console.log(`k1`, k1, 'k2', k2)
        let b = y - k2 * center[0]
        this.k2line_y = (x) => {
          return k2 * x + b
        }
        this.k2line_x = (y) => {
          return (y - b) / k2
        }
        //几个交点
        let m_top = [this.k2line_x(-h / 2), -h / 2]
        let m_right = [w / 2, this.k2line_y(w / 2)]
        let m_bottom = [this.k2line_x(h / 2), h / 2]
        let m_matrix_start = []

        //console.log('top', m_top)
        //console.log('right', m_right)
        //console.log('bottom', m_bottom)

        if (this.vertical == 0) {
          m_matrix_start = m_top
          //分别分析三个交点的情况，然后构建rect
          let [m_top_x] = m_top
          if (m_top_x < w / 2) {
            rect_back.push(m_top)
            rect_back.push(rt)

            rect_front.push(lt)
            rect_front.push(m_top)
          }
          let [, m_right_y] = m_right
          if (m_right_y > -h / 2 && m_right_y < h / 2) {
            rect_back.push(m_right)
            rect_front.push(m_right)
          }
          let [m_bottom_x] = m_bottom
          if (m_bottom_x < w / 2) {
            rect_back.push(rb)
            rect_back.push(m_bottom)

            rect_front.push(m_bottom)
          } else {
            rect_front.push(rb)
          }
          rect_front.push(lb)
        }
        if (this.vertical == 1) {
          m_matrix_start = m_bottom
          //分别分析三个交点的情况，然后构建rect
          let [m_bottom_x] = m_bottom
          if (m_bottom_x < w / 2) {
            rect_back.push(m_bottom)
            rect_back.push(rb)

            rect_front.push(lb)
            rect_front.push(m_bottom)
          }
          let [, m_right_y] = m_right
          if (m_right_y > -h / 2 && m_right_y < h / 2) {
            rect_back.push(m_right)
            rect_front.push(m_right)
          }
          let [m_top_x] = m_top
          if (m_top_x < w / 2) {
            rect_back.push(rt)
            rect_back.push(m_top)

            rect_front.push(m_top)
          } else {
            rect_front.push(rt)
          }
          rect_front.push(lt)
        }

        //center
        let axis1 = [0, 1]
        let axis2 = vec2.create()
        vec2.sub(axis2, m_matrix_start, center)
        let angle = vec2.angle(axis1, axis2)
        let cross = vec3.create()
        vec2.cross(cross, axis1, axis2)
        if (cross[2] == -1) {
          angle = -angle
        }
        //angle = (angle / Math.PI) * 180

        let m = mat2d.create()
        let m1 = mat2d.create()
        mat2d.translate(m1, m1, center)
        //console.log(center)

        let m2 = mat2d.create()
        mat2d.rotate(m2, m2, angle)
        let m3 = mat2d.create()
        mat2d.mul(m3, m1, m2)
        let m3_i = mat2d.create()
        mat2d.invert(m3_i, m3)
        //对称
        let m4 = mat2d.create()
        mat2d.scale(m4, m4, [-1, 1])
        mat2d.mul(m, m, m3)
        mat2d.mul(m, m, m4)
        mat2d.mul(m, m, m3_i)

        back_flip_matrix = m
      }

      this.rect.value = this.calculate_style({
        back: rect_back,
        front: rect_front,
        back_flip_matrix
      })
    }
    return this.rect.value
  }
  calculate(cb) {
    if (this.lock) return
    let { lt, lb, rb, rt } = this.corrds
    let { w, h } = this.options
    //let s_point = rt
    let { s_point: s, e_point: e } = this
    let e_point
    let s_point
    if (this.direction == 0) {
      if (e[1] >= s[1]) {
        e_point = [e[0] - s[0] + rt[0], e[1] - s[1] + rt[1]]
        s_point = rt
        this.vertical = 0
      } else {
        e_point = [e[0] - s[0] + rb[0], e[1] - s[1] + rb[1]]
        s_point = rb
        this.vertical = 1
      }
    } else {
      if (e[1] >= s[1]) {
        s_point = rt
        //e_point = [e[0] - s[0] + (-w / 2) * 3, e[1] - s[1] + lt[1]]
        e_point = [e[0] - s[0] + (-w / 2) * 3, rt[1]]
        this.vertical = 0
      } else {
        s_point = rb
        //e_point = [e[0] - s[0] + (-w / 2) * 3, e[1] - s[1] + lb[1]]
        e_point = [e[0] - s[0] + (-w / 2) * 3, rb[1]]
        this.vertical = 1
      }

      //这里变换设置calZ
    }

    if (this.direction == 0) {
      let dx = e_point[0] - s_point[0]
      // 这里不自动处理
      if (dx < -w / 2 && false) {
        this.lock = true
        this.toLeft(cb, {
          complete: () => {
            this.lock = false
          }
        })
      } else {
        this._fix_s_e_point(s_point, e_point)
        cb(this._calculate(s_point, e_point))
      }
    } else {
      this._fix_s_e_point(s_point, e_point)
      cb(this._calculate(s_point, e_point))
    }
  }
}
export class FlipUI extends Flip {
  constructor(options) {
    super(options)
    this.isStart = false
    this.front_img = options.front
    this.back_img = options.back
  }
  getPoint(e) {
    let { x, y } = e.target.getBoundingClientRect()
    let [touch] = e.touches
    x = 8
    y = 8
    //console.log(touch)
    let { clientX, clientY } = touch
    let point = [clientX - x - 50, clientY - y - 50]
    return point
  }
  onStart(e) {
    this.isStart = true
    this.s_point = this.getPoint(e)
    this.e_point = this.s_point
  }
  onMove(e) {
    if (this.isStart) {
      //console.log(e)
      let point = this.getPoint(e)
      this.e_point = point
      this.calculate(() => {})
    }
  }
  onEnd(e, options) {
    this.isStart = false
    this.toEnd(() => {}, options)
  }
}
